﻿using System;
using System.Configuration;
using System.Reflection;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Cfg.MappingSchema;
using NHibernate.Dialect;
using NHibernate.Mapping.ByCode;
using NHibernate.Tool.hbm2ddl;
using Configuration = NHibernate.Cfg.Configuration;

namespace SellAndBuy.Infrastructure.Data.Core.Factories
{
    /// <summary>
    /// Helper class for NHibernate connectoin and session factory
    /// </summary>
    public class NHibernateFactory
    {

        private readonly string _connectionString;
        private ISessionFactory _sessionFactory;
        private Configuration _configuration;



        /// <summary>
        /// Constructor
        /// </summary>
        public NHibernateFactory()
        {
            _connectionString = ConfigurationManager.ConnectionStrings["SellAndBuy"].ConnectionString;
        }



        /// <summary>
        /// Get session factory
        /// </summary>
        public ISessionFactory SessionFactory
        {
            get { return _sessionFactory ?? (_sessionFactory = CreateSessionFactory()); }
        }



        /// <summary>
        /// Create database schema
        /// </summary>
        public void CreateSchema()
        {
            if (_sessionFactory == null)
                _sessionFactory = CreateSessionFactory();

            new SchemaExport(_configuration).Execute(false, true, false);
        }



        /// <summary>
        /// Configure NHibernate
        /// </summary>
        private void ConfigureNHibernate()
        {
            _configuration = new Configuration();
            _configuration.DataBaseIntegration(x =>
            {
                x.Dialect<MsSql2008Dialect>();
                x.ConnectionString = _connectionString;
            });

            var mapper = new ModelMapper();
            var mappingAssemblies = ConfigurationManager.AppSettings["MappingAssemblies"].Split(';');
            foreach (var mappingAssembly in mappingAssemblies)
            {
                if(!String.IsNullOrWhiteSpace(mappingAssembly))
                    mapper.AddMappings(Assembly.Load(mappingAssembly).GetExportedTypes());
            }

            _configuration.AddDeserializedMapping(mapper.CompileMappingForAllExplicitlyAddedEntities() , "SellAndBuyDomain");
        }

        /// <summary>
        /// Create session factory
        /// </summary>
        /// <returns>session factory</returns>
        private ISessionFactory CreateSessionFactory()
        {
            ConfigureNHibernate();
            return _configuration.BuildSessionFactory();
        }

    }
}